Olaf adds writing to GDB.
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Fri, 29 Jul 2005 17:11:22 +0000 (17:11 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Fri, 29 Jul 2005 17:11:22 +0000 (17:11 +0000)
gpsbabel/README
gpsbabel/gdb.c
gpsbabel/reference/gdb-sample.gpx
gpsbabel/testo

index dd6a205cedabe811e39b50fd8323a6a9c6207ff2..c18bf5ac83cc09725a6c1ee3d6e621376bb814f0 100644 (file)
@@ -873,10 +873,20 @@ THE FORMATS
 
     GDB
 
-        Support for the "Garmin GPS Database" format used by default
-        in MapSource versions 6.1 and later. With this first step you
-        should be able to read waypoints, routes and tracks from .gdb
-        files.
+        Support for the "Garmin GPS Database" format used by default in
+        MapSource versions since release 6.0. By default we create gdb's
+        of version 2.  Version 2 is used in Mapsource 6.3 and 6.5.
+
+        Garmin GPS database is an undocumented file format. The
+        basic info for this module comes from the existing MapSource
+        conversion code.
+
+        Additional options:
+
+            ver - set the data format version of the output file
+            (currently 1 or 2); 2 is our default.
+            via - Drop hidden route points (means calculated stuff) 
+           cat - default category on output (1..16)
 
     BCR
     
index b5eb8cf954b5193f89eae3dbc4d48f5ea71b1e40..a0ccebe2cd99ff1656cec6647f66456f10a4b972 100644 (file)
@@ -1,5 +1,5 @@
 /* 
-       Garmin GPS Database Reader
+       Garmin GPS Database Reader/Writer
        
        Copyright (C) 2005 Olaf Klein, o.b.klein@t-online.de
        Mainly based on mapsource.c,
        Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
 */
 
+/*
+       History:
+       
+           2005/06/27: initial release (reader only)
+           2005/07/26: added write support
+           2005/07/27: replaced "tricky code" in route reader
+           2005/07/28: fixed handling of single point routes
+                       new option "via"
+                       new option "ver"
+                       fixed compiler warnings
+*/
+
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 
 #define MYNAME "gdb"
 
-#define MPSNAMEBUFFERLEN       1024
-#define MPSNOTESBUFFERLEN      4096
-#define MPSDESCBUFFERLEN       4096
+#undef GDB_DEBUG
+
+#define GDB_VER_MIN                    1
+#define GDB_VER_MAX                    2
+
+#define GDB_DEFAULTWPTCLASS            0
+#define GDB_HIDDENROUTEWPTCLASS                8
+
+#define GDB_NAME_BUFFERLEN     1024
+#define GDB_NOTES_BUFFERLEN    4096
+#define GDB_DESCR_BUFFERLEN    4096
 
 #define DEFAULTICONVALUE       18
 #define DEFAULTICONDESCR       "Waypoint"
 
 /* %%% local vars %%% */
 
-FILE *fin;
-static char *fin_name;
+FILE *fin, *fout;
+static char *fin_name, *fout_name;
+
 static int gdb_ver = 1;
 static int gdb_debug = 0;
-route_head *gdb_hidden;
+static int gdb_via;            /* 0 = read and write hidden points too; 1 = drop */
+static int gdb_category;
+
+route_head *gdb_hidden = NULL;
+
+
+#define GDB_OPT_VER            "ver"
+#define GDB_OPT_VIA            "via"
+#define GDB_OPT_CATEGORY       "cat"
+
+static char *gdb_opt_category = NULL;
+static char *gdb_opt_ver = NULL;
+static char *gdb_opt_via = NULL;
+
+static arglist_t gdb_args[] = {
+       {GDB_OPT_CATEGORY, &gdb_opt_category, 
+           "Default category on output (1..16)", NULL, ARGTYPE_INT},
+       {GDB_OPT_VER, &gdb_opt_ver, 
+           "Version of gdb file to generate (1,2)", "2", ARGTYPE_INT},
+       {GDB_OPT_VIA, &gdb_opt_via, 
+           "Drop route points, if they don't have an aquivalent waypoint (hidden points)", NULL, ARGTYPE_BOOL},
+       {0, 0, 0, 0, 0}
+};
+
+/********************************************************************************************************/
 
 /* %%% 1-1 functions from mapsource, should by shared!!! %%% */
 
+/*
+ * Add a waypoint that we've already written out to our list
+ *
+ */
+void
+gdb_add_to_hidden(const waypoint *wpt)
+{
+       waypoint *tmp = waypt_dupe(wpt);
+       route_add_wpt(gdb_hidden, tmp);
+}
+
 waypoint *
 gdb_find_wpt_q_by_name(const queue *whichQueue, const char *name)
 {
@@ -72,8 +128,15 @@ gdb_find_wpt_q_by_name(const queue *whichQueue, const char *name)
 const char *
 gdb_find_desc_from_icon_number(const int icon, garmin_formats_e garmin_format)
 {
+       static char custom[] = "Custom 63";
        icon_mapping_t *i;
 
+       if (icon >= 500 && icon <= 563)
+       {
+           snprintf(custom, sizeof(custom), "Custom %d", icon - 500);
+           return &custom[0];
+       }
+
        for (i = garmin_icon_table; i->icon; i++) {
                switch (garmin_format) {
                        case MAPSOURCE:
@@ -92,6 +155,51 @@ gdb_find_desc_from_icon_number(const int icon, garmin_formats_e garmin_format)
        return DEFAULTICONDESCR;
 }
 
+int
+gdb_find_icon_number_from_desc(const char *desc, garmin_formats_e garmin_format)
+{
+       icon_mapping_t *i;
+       int def_icon = DEFAULTICONVALUE;
+       int n;
+
+       if (!desc)
+               return def_icon;
+
+       /*
+        * If we were given a numeric icon number as a description 
+        * (i.e. 8255), just return that.
+        */
+       n = atoi(desc);
+       if (n)  {
+               return n;
+       }
+
+       for (i = garmin_icon_table; i->icon; i++) {
+               if (case_ignore_strcmp(desc,i->icon) == 0) {
+                       switch (garmin_format) {
+                       case MAPSOURCE:
+                               return i->mpssymnum;
+                       case PCX:
+                       case GARMIN_SERIAL:
+                               return i->pcxsymnum;
+                       default:
+                               fatal(MYNAME ": unknown garmin format");
+                       }
+               }
+       }
+       return def_icon;
+}
+
+int
+gdb_detect_rtept_class(const waypoint *wpt)
+{
+       if (gdb_find_wpt_q_by_name((queue *)&gdb_hidden->waypoint_list, wpt->shortname) == NULL)
+           return (int)GDB_HIDDENROUTEWPTCLASS;
+       else
+           return (int)GDB_DEFAULTWPTCLASS;
+}
+
+
 #ifndef UTF8_SUPPORT
 char *gdb_garmin_to_utf8(const char *s)
 {
@@ -172,31 +280,32 @@ gdb_create_rte_wpt(const char *name, double lat, double lon, double alt)
        waypoint *wpt;
        
        wpt = find_waypt_by_name(name);
-       if (wpt != NULL) wpt = waypt_dupe(wpt);
+       if (wpt == NULL)
+       {
+           if (gdb_via != 0) return NULL;
+           wpt = gdb_find_wpt_q_by_name((queue *)&gdb_hidden->waypoint_list, name);
+       }
+       if (wpt != NULL) 
+               wpt = waypt_dupe(wpt);
        else
        {
-           gdb_find_wpt_q_by_name((queue *)&gdb_hidden->waypoint_list, name);
-           if (wpt != NULL) wpt = waypt_dupe(wpt);
-           else
-           {
-               wpt = waypt_new();
-               wpt->shortname = xstrdup(name);
-               wpt->latitude = lat;
-               wpt->longitude = lon;
-               wpt->altitude = alt;
-               wpt->depth = unknown_alt;
-           }
+           wpt = waypt_new();
+           wpt->shortname = xstrdup(name);
+           wpt->latitude = lat;
+           wpt->longitude = lon;
+           wpt->altitude = alt;
+           wpt->depth = unknown_alt;
        }
        return wpt;
 }
 
-static size_t
-gdb_fread(void *target, size_t size, size_t count, FILE *fin)
+size_t
+gdb_fread(void *target, size_t size)
 {
        size_t result;
 
-       result = fread(target, size, count, fin);
-       if (result < count)
+       result = fread(target, 1, size, fin);
+       if (result < size)
        {
            if (feof(fin) != 0)
                fatal(MYNAME ": unexpected end of file \"%s\"!\n", fin_name);
@@ -206,8 +315,8 @@ gdb_fread(void *target, size_t size, size_t count, FILE *fin)
        return result;
 }
 
-static int
-gdb_fread_str(FILE *fin, char *dest, size_t maxlen)
+int
+gdb_fread_str(char *dest, size_t maxlen)
 {
        int c;
        int res = 0;
@@ -232,8 +341,8 @@ gdb_fread_str(FILE *fin, char *dest, size_t maxlen)
        fatal(MYNAME ": local buffer overflow detected, please report!\n");
 }
 
-static int
-gdb_fread_le(FILE *fin, void *dest, size_t size, int bit_count, const char *field)
+int
+gdb_fread_le(void *dest, size_t size, int bit_count, const char *prefix, const char *field)
 {
        char buff[32];
        unsigned char *c = dest;
@@ -242,47 +351,90 @@ gdb_fread_le(FILE *fin, void *dest, size_t size, int bit_count, const char *fiel
        double *db = dest;
        
        if ((bit_count >> 3) != size)
-           fatal(MYNAME ": internal error (gdb_le_read/%d/%d/%s)!\n", size, bit_count >> 3, field);
+           fatal(MYNAME "%s: Internal error (gdb_le_read/%d/%d/%s)!\n", prefix, (int)size, bit_count >> 3, field);
            
        switch(bit_count)
        {
            case 8:
-               gdb_fread(c, sizeof(*c), 1, fin);
-               if (gdb_debug) printf(MYNAME ": gdb_fread_le : %d -> %s (0x%x))\n", *c, field, *c);
+               gdb_fread(c, sizeof(*c));
+               if (gdb_debug)
+                   printf(MYNAME "%s: gdb_fread_le : %d -> %s (0x%x))\n", prefix, *c, field, *c);
                return *c;
            case 16:
                if (sizeof(*sh) != size) fatal(MYNAME ": internal decl.!\n");
-               gdb_fread(sh, sizeof(*sh), 1, fin);
+               gdb_fread(sh, sizeof(*sh));
                *sh = le_read16(sh);
-               if (gdb_debug) printf(MYNAME ": gdb_fread_le : %d -> %s (0x%x))\n", *sh, field, *sh);
+               if (gdb_debug)
+                   printf(MYNAME "%s: gdb_fread_le : %d -> %s (0x%x))\n", prefix, *sh, field, *sh);
                return *sh;
            case 32:
-               gdb_fread(li, 4, 1, fin);
+               gdb_fread(li, 4);
                *li = le_read32(li);
-               if (gdb_debug) printf(MYNAME ": gdb_fread_le : %d -> %s (0x%x)\n", *li, field, *li);
+               if (gdb_debug)
+                   printf(MYNAME "%s: gdb_fread_le : %d -> %s (0x%x)\n", prefix, *li, field, *li);
                return *li;
            case 64:
-               gdb_fread(buff, sizeof(*db), 1, fin);
+               gdb_fread(buff, sizeof(*db));
                le_read64(db, buff);
-               if (gdb_debug) printf(MYNAME ": gdb_fread_le : %g -> %s\n", *db, field);
+               if (gdb_debug)
+                   printf(MYNAME "%s: gdb_fread_le : %g -> %s\n", prefix, *db, field);
                return 0;
            default:
-               fatal(MYNAME ": unsupported bit count (%d) in gdb_le_read!\n", bit_count);          
+               fatal(MYNAME "%s: unsupported bit count (%d) in gdb_le_read!\n", prefix, bit_count);        
        }
 }
 
-static void
-gdb_is_valid(int is, const char *comment)
+int
+gdb_fread_flag(const char value)       /* read one byte and compare to value */
 {
-       if (is == 0) fatal(MYNAME ": error in database structure (%s)!\n", comment);
+       char c;
+
+       gdb_fread(&c, 1);
+       return (c == value);
 }
 
-static void
+void
+gdb_is_valid(int is, const char *prefix, const char *comment)
+{
+       if (is == 0) 
+       {
+           printf(MYNAME ": Reading database \"%s\"\n", fin_name);
+           fatal(MYNAME  "-%s: Found error in data (%s)!\n", prefix, comment);
+       }
+}
+
+void
+gdb_is_validf(int is, const char *prefix, const char *format, ...)
+{
+       va_list args;
+       char buff[256];
+       
+       if (is != 0) return;
+       
+       va_start(args, format);
+       if (fin_name != NULL)
+           printf(MYNAME "-%s: Reading from database \"%s\"\n", prefix, fin_name);
+       else
+           printf(MYNAME "-%s: Writing to database \"%s\"\n", prefix, fout_name);
+       printf(MYNAME "-%s: ");
+       vprintf(format, args);
+       puts("");
+       
+       va_end(args);
+       fatal("");
+}
+
+/********************************************************************************************************/
+/* %%%                                   read file header                                               */
+/********************************************************************************************************/
+
+void
 gdb_read_file_header(void)
 {
        char buff[128];
        int i, reclen;
 
+       const char *prefix = "read_head";
 /* 
        We starts with standard binary read.
        A gdb_fread_str works too, but if we get a wrong file as input,
@@ -293,17 +445,18 @@ gdb_read_file_header(void)
 */
        
        if (6 != fread(buff, 1, 6, fin))
-           fatal(MYNAME ": invalid file \"%s\"!\n", fin_name);
+           fatal(MYNAME ": Invalid file \"%s\"!\n", fin_name);
            
        if (strcmp(buff, "MsRcf") != 0)
-           fatal(MYNAME ": invalid file \"%s\"!\n", fin_name);
+           fatal(MYNAME ": Invalid file \"%s\"!\n", fin_name);
            
-       gdb_fread(&reclen, 4, 1, fin);
+       gdb_fread(&reclen, 4);
        reclen = le_read32(&reclen);
        
-       gdb_is_valid(reclen == gdb_fread_str(fin, buff, sizeof(buff)), "header");
-       
-       gdb_is_valid(buff[0] == 'D', "header");
+       gdb_is_valid(reclen == gdb_fread_str(buff, sizeof(buff)), prefix, "Invalid record length");
+       if (buff[0] != 'D')
+           fatal(MYNAME ": Invalid file \"%s\"!\n", fin_name);
+
        switch(buff[1])
        {
            case 'k':
@@ -313,40 +466,44 @@ gdb_read_file_header(void)
                gdb_ver = 2;
                break;
            default:
-               fatal(MYNAME ": non supported gdb version!\n");
+               fatal(MYNAME ": Non supported GDB version!\n");
        }
        
        if (global_opts.verbose_status > 0)
-           printf(MYNAME ": found Garmin GPS Database version %d\n", gdb_ver);
+           printf(MYNAME ": Found Garmin GPS Database version %d.0\n", gdb_ver);
        
-       gdb_fread(&reclen, 4, 1, fin);
+       gdb_fread(&reclen, 4);
        reclen = le_read32(&reclen);
-       gdb_is_valid(reclen < sizeof(buff), "header");
-       gdb_fread(buff, reclen, 1, fin);
+       gdb_is_valid(reclen < sizeof(buff), prefix, "Invalid record length");
+       gdb_fread(buff, reclen);
        
-       gdb_is_valid(0 == gdb_fread_str(fin, buff, sizeof(buff)), "header");
+       gdb_is_valid(0 == gdb_fread_str(buff, sizeof(buff)), prefix, "header");
        
-       i = gdb_fread_str(fin, buff, sizeof(buff));
-       gdb_is_valid((i == 9) && (strcmp(buff, "MapSource") == 0), "header");
+       i = gdb_fread_str(buff, sizeof(buff));
+       gdb_is_valid((i == 9) && (strcmp(buff, "MapSource") == 0), prefix, "MapSource magic");
 }
 
+/********************************************************************************************************/
+/* %%%                                     read waypoint                                               */
+/********************************************************************************************************/
+
 waypoint *
 gdb_read_wpt(const size_t fileofs, int *wptclass)
 {
-       char xname[MPSNAMEBUFFERLEN];
-       char xdesc[MPSDESCBUFFERLEN];
-       char xnotes[MPSNOTESBUFFERLEN];
+       char xname[GDB_NAME_BUFFERLEN];
+       char xdesc[GDB_DESCR_BUFFERLEN];
+       char xnotes[GDB_NOTES_BUFFERLEN];
        int xclass;
        int xlat, xlon, xdisplay, xcolour, xicon, xtime;
        short xcat;
        double xdepth = unknown_alt;
        double xalt = unknown_alt;
+       double xproximity = unknown_alt;
        waypoint *res;
-
-       char *ctmp;
        char buff[128];
-       
        size_t pos, delta;
+       
+       const char *prefix = "wpt_read";
 
        
 /********************************************************************************************************/
@@ -377,67 +534,53 @@ gdb_read_wpt(const size_t fileofs, int *wptclass)
  */    
 /********************************************************************************************************/
 
-       gdb_is_valid(gdb_fread_str(fin, xname, sizeof(xname)) > 0, "new waypoint");
+       gdb_is_valid(gdb_fread_str(xname, sizeof(xname)) > 0, prefix, "new waypoint");
        gdb_convert_name_buff(xname, sizeof(xname));
 
-       gdb_fread_le(fin, &xclass, sizeof(xclass), 32, "xclass");
-       gdb_fread_str(fin, buff, sizeof(buff));                         /* country */
+       gdb_fread_le(&xclass, sizeof(xclass), 32, prefix, "class");
+       gdb_fread_str(buff, sizeof(buff));                              /* country */
        
-       gdb_fread(buff, 22, 1, fin);
-       xlat = gdb_fread_le(fin, &xlat, sizeof(xlat), 32, "xlat");      /* latitude */
-       xlon = gdb_fread_le(fin, &xlon, sizeof(xlon), 32, "xlon");      /* latitude */
+       gdb_fread(buff, 22);
+       xlat = gdb_fread_le(&xlat, sizeof(xlat), 32, prefix, "latitude");
+       xlon = gdb_fread_le(&xlon, sizeof(xlon), 32, prefix, "longitude");
        
-       gdb_fread(buff, 1, 1, fin);
-       if (buff[0] == 1)                                               /* altitude flag */
-       {
-           gdb_fread_le(fin, &xalt, sizeof(xalt), 64, "xalt");         /* altitude */
-       }
+       if (gdb_fread_flag(1))                                          /* altitude flag */
+           gdb_fread_le(&xalt, sizeof(xalt), 64, prefix, "altitude");
        
-       gdb_fread_str(fin, xdesc, sizeof(xdesc));
+       gdb_fread_str(xdesc, sizeof(xdesc));                            /* description */
        gdb_convert_name_buff(xdesc, sizeof(xdesc));
        
-       gdb_fread(buff, 1, 1, fin);                                     /* proximity flag */
-       if (buff[0] == 1) 
-       {
-           gdb_fread(buff, 8, 1, fin);                                 /* proximity */
-       }
+       if (gdb_fread_flag(1))                                          /* proximity flag */
+           gdb_fread_le(&xproximity, sizeof(xproximity), 64, prefix, "proximity");
        
-       xdisplay = gdb_fread_le(fin, &xdisplay, sizeof(xdisplay), 32, "xdisplay");
-       xcolour = gdb_fread_le(fin, &xcolour, sizeof(xcolour), 32, "xcolour");
-       xicon = gdb_fread_le(fin, &xicon, sizeof(xicon), 32, "xicon");
+       xdisplay = gdb_fread_le(&xdisplay, sizeof(xdisplay), 32, prefix, "display");
+       xcolour = gdb_fread_le(&xcolour, sizeof(xcolour), 32, prefix, "colour");
+       xicon = gdb_fread_le(&xicon, sizeof(xicon), 32, prefix, "icon");
 
-       /* ToDo: convert the icon !!! */
-               
-       gdb_fread_str(fin, buff, sizeof(buff));                         /* city */
-       gdb_fread_str(fin, buff, sizeof(buff));                         /* state */
-       gdb_fread_str(fin, buff, sizeof(buff));                         /* facility */
-       gdb_fread(buff, 1, 1, fin);                                     /* unknown */
+       gdb_fread_str(buff, sizeof(buff));                              /* city */
+       gdb_fread_str(buff, sizeof(buff));                              /* state */
+       gdb_fread_str(buff, sizeof(buff));                              /* facility */
        
-       gdb_fread(buff, 1, 1, fin);                                     /* depth flag */
-       if (buff[0] == 1) 
-       {
-           gdb_fread_le(fin, &xdepth, sizeof(xdepth), 64, "xdepth");   /* depth */
-       }
+       gdb_fread(buff, 1);                                             /* unknown */
        
-       gdb_fread(buff, 1, 1, fin);
-       gdb_fread(buff, 1, 1, fin);
-       gdb_fread(buff, 1, 1, fin);
+       if (gdb_fread_flag(1))                                          /* depth flag */
+           gdb_fread_le(&xdepth, sizeof(xdepth), 64, prefix, "depth");
        
-       if (buff[0] != 0)
-           gdb_fread(buff, 3, 1, fin);
+       gdb_fread(buff, 1);
+       gdb_fread(buff, 1);
+
+       if (gdb_fread_flag(0))
+           gdb_fread(buff, 4);
        else
-           gdb_fread(buff, 4, 1, fin);
+           gdb_fread(buff, 3);
 
-       gdb_fread_str(fin, xnotes, sizeof(xnotes));
+       gdb_fread_str(xnotes, sizeof(xnotes));
        gdb_convert_name_buff(xnotes, sizeof(xnotes));
        
-       xcat = gdb_fread_le(fin, &xcat, sizeof(xcat), 16, "xcat");
+       xcat = gdb_fread_le(&xcat, sizeof(xcat), 16, prefix, "category");
        
-       gdb_fread(buff, 1, 1, fin);                                     /* temperature flag */
-       if (buff[0] == 1) 
-       {
-           gdb_fread(buff, 8, 1, fin);                                 /* temperature */
-       }
+       if (gdb_fread_flag(1))                                          /* temperature flag */
+           gdb_fread(buff, 8);                                         /* temperature */
 
        /* Here comes 1 .. 6 unknown bytes
           !!! 6 only if class > 0 !!!
@@ -445,23 +588,22 @@ gdb_read_wpt(const size_t fileofs, int *wptclass)
        
        pos = ftell(fin);
        delta = fileofs - pos;
-       gdb_is_valid(delta > 0, "waypoint final");
+       gdb_is_valid(delta > 0, prefix, "waypoint final");
        
        if ((delta & 1) == 0)
        {
-           gdb_fread(buff, 1, 1, fin);
+           gdb_fread(buff, 1);
            delta--;
        }
        
        xtime = 0;
-       gdb_fread(buff, 1, 1, fin);
-       if (buff[0] == 1)
+       if (gdb_fread_flag(1))
        {
-           gdb_is_valid(delta==5, "??? waypoint time ???");
-           gdb_fread_le(fin, &xtime, sizeof(xtime), 32, "xtime");
+           gdb_is_valid(delta==5, prefix, "Waypoint time");
+           gdb_fread_le(&xtime, sizeof(xtime), 32, prefix, "time");
        }
            else
-               gdb_is_valid(delta==1, "no waypoint time");
+               gdb_is_valid(delta==1, prefix, "No waypoint time");
        
        *wptclass = xclass;
        
@@ -472,204 +614,182 @@ gdb_read_wpt(const size_t fileofs, int *wptclass)
        res->latitude = GPS_Math_Semi_To_Deg(xlat);
        res->longitude = GPS_Math_Semi_To_Deg(xlon);
        res->altitude = xalt;
+       res->depth = xdepth;
+       res->proximity = xproximity;
        res->creation_time = xtime;
+#if 0
+       res->garmin_data = xcalloc(1, sizeof(garmin_data_t));
+       res->garmin_data->colour = xcolour;
+       res->garmin_data->category = xcat;
+       res->garmin_data->display = xdisplay;
+#endif
        /* might need to change this to handle version dependent icon handling */
        res->icon_descr = gdb_find_desc_from_icon_number(xicon, MAPSOURCE);
-       
-       gdb_is_valid(fabs(res->latitude) <= 90.0 && fabs(res->longitude) <= 180.0, " - wpt read: invalid lat or lon");
+
+       gdb_is_validf(fabs(res->latitude) <= 90.0, prefix, "%s has invalid latitude (%f)", 
+           res->shortname, res->latitude);
 
        return res;
 }
 
+/********************************************************************************************************/
+/* %%%                                     read route                                                   */
+/********************************************************************************************************/
+
 route_head *
 gdb_read_route(void)
 {
-       char xname[MPSNAMEBUFFERLEN];
-       char xwptname[MPSNAMEBUFFERLEN];
+       char xname[GDB_NAME_BUFFERLEN];
+       char xwptname[GDB_NAME_BUFFERLEN];
        int xclass;
        double xalt;
-       double xlat, xlon;
+       double xlat = 0;        /* compiler warnings */
+       double xlon = 0;        /* compiler warnings */
        
        char buff[256];
-       int count;
-       int checked;
+       int count, origin;
        int isteps, ilink;
        int semilat, semilon;
+       int maxlat, maxlon, minlon, minlat;
+       char auto_name;
        
        route_head *route;
        waypoint *wpt;
        
-       int i, j;
-       size_t curpos;
+       const char *prefix =  "rte_read_head";
+       const char *prefix1 = "rte_read_loop";
+       const char *prefix2 = "rte_ils_loop";
+       const char *prefix3 = "rte_read_final";
        
-       gdb_is_valid(gdb_fread_str(fin, xname, sizeof(xname)) > 0, "route start");
+       gdb_is_valid(gdb_fread_str(xname, sizeof(xname)) > 0, prefix, "Route has no name");
        gdb_convert_name_buff(xname, sizeof(xname));
-
-       gdb_fread_le(fin, buff, 2, 16, "auto_name");
-       gdb_fread_le(fin, buff, 4, 32, "max_lat");
-       gdb_fread_le(fin, buff, 4, 32, "max_lon");
        
-       gdb_fread(buff, 1, 1, fin);
-       if (buff[0] == 1) gdb_fread_le(fin, buff, 8, 64, "max_alt");
+       gdb_fread_le(&auto_name, sizeof(auto_name), 8, prefix, "auto name");
+       if (gdb_fread_flag(0))                                  /* max. data flag */
+       {
+           gdb_fread_le(buff, 4, 32, prefix, "max. latitude");
+           gdb_fread_le(buff, 4, 32, prefix, "max. longitude");
+       
+           gdb_fread(buff, 1);
+           if (buff[0] == 1) gdb_fread_le(buff, 8, 64, prefix, "max. altitude");
            
-       gdb_fread_le(fin, buff, 4, 32, "min_lat");
-       gdb_fread_le(fin, buff, 4, 32, "min_lon");
+           gdb_fread_le(buff, 4, 32, prefix, "min. latitude");
+           gdb_fread_le(buff, 4, 32, prefix, "min. longitude");
 
-       gdb_fread(buff, 1, 1, fin);
-       if (buff[0] == 1) gdb_fread_le(fin, buff, 8, 64, "min_alt");
+           gdb_fread(buff, 1);
+           if (buff[0] == 1)
+               gdb_fread_le(buff, 8, 64, prefix, "min. altitude");
+       }
            
-       gdb_fread_le(fin, &count, sizeof(count), 32, "rte_count");
-       if (count <= 0) return NULL;
+       gdb_fread_le(&count, sizeof(count), 32, prefix, "count");
+       
+       if (count == 0) 
+           fatal(MYNAME "%s: !!! Empty routes are not allowed !!!\n", prefix);
        
        route = route_head_alloc();
        route->rte_name = xstrdup(xname);
        route_add_head(route);
 
-#if GDB_DEBUG
-       printf(MYNAME " - route: \"%s\" with %d point(s)\n", route->rte_name, count);
+#ifdef GDB_DEBUG
+       printf(MYNAME " - route: \"%s\" with %d point(s)\n", xname, count);
 #endif
-       
-       if (count <= 0) return route;
-       
-       count--;
+       origin = count;
        
        while (count--)
        {
-           gdb_fread_str(fin, xwptname, sizeof(xwptname));             /* name */
+           gdb_fread_str(xwptname, sizeof(xwptname));                  /* waypoint name */
            gdb_convert_name_buff(xwptname, sizeof(xwptname));
+       
+           gdb_fread_le(&xclass, sizeof(xclass), 32, prefix1, "class");        /* class */
+           gdb_fread_str(buff, sizeof(buff));                                  /* country */
            
-           gdb_fread_le(fin, &xclass, sizeof(xclass), 32, "xclass");   /* class */
-           gdb_fread_str(fin, buff, sizeof(buff));                     /* country */
-           
-           gdb_fread(buff, 22, 1, fin);                                /* sub class data */
-           i = 0;
-           while (i < sizeof(buff))
-           {
-               gdb_fread(&buff[i], 1, 1, fin);
-               if (buff[i] == 0) break;
-               i++;
-           } 
+           gdb_fread(buff, 22);                                                /* sub class data */
+           gdb_fread(buff, 1);
+           gdb_is_valid(buff[0] == 0, prefix1, "Should by zero byte (1)");
 
            /* The next thing is the unknown 0x03 0x00 .. 0x00 (18 bytes) */
-           gdb_fread(buff, 18, 1, fin);
-           
-           gdb_fread_le(fin, &isteps, sizeof(isteps), 32, "isteps");
+           /* OK: this should be, but i've seen exceptions (...cannot verify the first byte */
+           gdb_fread(buff, 18); 
+
+           gdb_fread_le(&isteps, sizeof(isteps), 32, prefix1, "interlink steps");
            
-           if (isteps <= 0) return route;      
+           if (isteps <= 0)                                            /* ??? end of route or error ??? */
+           {
+               gdb_is_valid(count == 0, prefix3, "Zero interlink steps within route");
+               
+               gdb_fread(buff, 1);
+               gdb_is_valid((buff[0] == 1), prefix3, "last seq.(1)");
+               
+               if (gdb_ver > 1)
+                   gdb_fread(buff, 8);                                 /* Unknown 8 bytes since gdb v2 */
+
+               gdb_fread(buff, 1);
+               gdb_is_valid((buff[0] == 0), prefix3, "last seq.(2)");
+               
+               wpt = gdb_create_rte_wpt(xwptname, xlat, xlon, xalt);
+               if (wpt != NULL)
+                   route_add_wpt(route, wpt);
+               return route;
+           }
            
-           gdb_fread_le(fin, &semilat, sizeof(semilat), 32, "semilat");
-           gdb_fread_le(fin, &semilon, sizeof(semilon), 32, "semilon");
+           gdb_fread_le(&semilat, sizeof(semilat), 32, prefix1, "semi-latitude");
+           gdb_fread_le(&semilon, sizeof(semilon), 32, prefix1, "semi-longitude");
            xlat = GPS_Math_Semi_To_Deg(semilat);
            xlon = GPS_Math_Semi_To_Deg(semilon);
            
-           gdb_is_valid(fabs(xlat) <= 90.0 && fabs(xlon) <= 180.0, " - rte: read loop: invalid lat or lon");
+           gdb_is_validf(fabs(xlat) <= 90.0, prefix1, "Invalid latitude (%f)", xlat);
            
-           xalt = unknown_alt;
-           gdb_fread(buff, 1, 1, fin);                         /* altitude flag */
-           if (buff[0] == 1)
-           {
-               gdb_fread_le(fin, &xalt, sizeof(xalt), 64, "xalt");
-           }
+           if (gdb_fread_flag(1))                                      /* altitude flag */
+               gdb_fread_le(&xalt, sizeof(xalt), 64, prefix1, "altitude");
+           else
+               xalt = unknown_alt;
 
            wpt = gdb_create_rte_wpt(xwptname, xlat, xlon, xalt);
-           route_add_wpt(route, wpt);
+           if (wpt != NULL)
+               route_add_wpt(route, wpt);
            
-           for (ilink = isteps-1; ilink > 0; ilink--)
+           while (--isteps > 0)
            {
-               gdb_fread_le(fin, &semilat, sizeof(semilat), 32, "semilat");
-               gdb_fread_le(fin, &semilon, sizeof(semilon), 32, "semilon");
-               gdb_fread(buff, 1, 1, fin);                             /* altitude flag */
-               if (buff[0] == 1) gdb_fread_le(fin, &xalt, sizeof(xalt), 64, "xalt");
+               gdb_fread_le(&semilat, sizeof(semilat), 32, prefix2, "semi-latitude");
+               gdb_fread_le(&semilon, sizeof(semilon), 32, prefix2, "semi-longitude");
+               gdb_fread(buff, 1);                             /* altitude flag */
+               if (buff[0] == 1)
+                   gdb_fread_le(&xalt, sizeof(xalt), 64, prefix2, "altitude");
+
                xlat = GPS_Math_Semi_To_Deg(semilat);
                xlon = GPS_Math_Semi_To_Deg(semilon);
-               gdb_is_valid(fabs(xlat) <= 90.0 && fabs(xlon) <= 180.0, " - rte/ils: read loop: invalid lat or lon");
+               gdb_is_validf(fabs(xlat) <= 90.0, prefix2, "Invalid latitude (%f)", xlat);
            }
            
-           gdb_fread(buff, 1, 1, fin);                 /* NULL */
-           gdb_is_valid(buff[0] == 0, "should be zero byte");
-
-           gdb_fread(buff, 4, 1, fin);                         /* link max lat */
-           gdb_fread(buff, 4, 1, fin);                         /* link max lon */
-           gdb_fread(buff, 1, 1, fin);
-           if (buff[0] == 1) 
-           {
-               gdb_fread(buff, 8, 1, fin);                     /* link max alt validity + alt */
-           }
-           gdb_fread(buff, 4, 1, fin);                         /* link min lat */
-           gdb_fread(buff, 4, 1, fin);                         /* link min lon */
+           gdb_fread(buff, 1);
+           gdb_is_valid(buff[0] == 0, prefix1, "\"Zero\" byte expected");
 
-           gdb_fread(buff, 1, 1, fin);
-           if (buff[0] == 1) 
-           {
-               gdb_fread(buff, 8, 1, fin);                     /* link min alt validity + alt */
-           }
+           gdb_fread_le(&maxlat, sizeof(maxlat), 32, prefix1, "max. latitude");
+           gdb_fread_le(&maxlon, sizeof(maxlon), 32, prefix1, "max. longitude");
 
-           /* find the end of the record */
+           if (gdb_fread_flag(1))                              /* link max alt validity + alt */
+               gdb_fread(buff, 8);                             
 
-           curpos = ftell(fin);
-           
-           /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-           the stuff here is very tricky and did not base on any 
-           any knowledgement, but seems to work.
-           The final structure varied from file to file and i 
-           could not find any connection with data, gdb version
-           and any unknown bytes and bits. Hmm.
-           !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+           gdb_fread_le(&minlat, sizeof(minlat), 32, prefix1, "min. latitude");
+           gdb_fread_le(&minlon, sizeof(minlon), 32, prefix1, "min. longitude");
 
-           memset(buff, 0, sizeof(buff));
-           checked = 0;
-
-           j = 18;
-           while (checked == 0 && j-- > 0)
-           {
-               for (i=1; i<8; i++) buff[i-1] = buff[i];
-               gdb_fread(&buff[7], 1, 1, fin);
-               for (i=0; i<8; i++)
-               {
-                   if (buff[i] != -1) break;
-                   if (i == 7) checked = 1;
-               }
+           if (gdb_fread_flag(1))                              /* link min alt validity + alt */
+               gdb_fread(buff, 2 * sizeof(int));                               
                
-           }
-           if (checked == 0)
-           {
-               fseek(fin, curpos, SEEK_SET);
-           }
-           else
-           {
-               while (1)
-               {
-                   gdb_fread(buff, 1, 1, fin);
-                   if (buff[0] != -1)
-                   {
-                       fseek(fin, ftell(fin)-1, SEEK_SET);
-                       break;          
-                   }
-               }
-               
-           }
+           if (gdb_ver > 1)
+               gdb_fread(buff, 8);                             /* unknown 8 bytes since gdb v2 */
        }
        
-       gdb_fread_str(fin, xwptname, sizeof(xwptname));                 /* name */
-       gdb_convert_name_buff(xwptname, sizeof(xwptname));
-           
-#if GDB_DEBUG
-       printf(MYNAME " - rte/fin: \"%s\"\n", xwptname);
-#endif
-       gdb_fread_le(fin, &xclass, sizeof(xclass), 32, "xclass");       /* class */
-       gdb_fread_str(fin, buff, sizeof(buff));                         /* country */
-           
-       wpt = gdb_create_rte_wpt(xwptname, xlat, xlon, xalt);
-       route_add_wpt(route, wpt);
+       /* This should normally never happen; end of route is handled in main loop before this */
        
-       return route;
+       fatal(MYNAME "-%s: Unexpected end of route \"%s\"!", prefix1, xname);
 }
 
 
 route_head *
 gdb_read_track(const size_t max_file_pos)
 {
-       char xname[MPSNAMEBUFFERLEN];
+       char xname[GDB_NAME_BUFFERLEN];
        unsigned char xdisplay;
        int xcolour;
        int xlat;
@@ -685,39 +805,40 @@ gdb_read_track(const size_t max_file_pos)
        route_head *track;
        waypoint *wpt;
        
-       gdb_fread_str(fin, xname, sizeof(xname));
+       const char *prefix0 = "trk_read";
+       const char *prefix = "trk_read_loop";
+       
+       gdb_fread_str(xname, sizeof(xname));
        gdb_convert_name_buff(xname, sizeof(xname));
        
-       gdb_fread_le(fin, &xdisplay, sizeof(xdisplay), 8, "xdisplay");
-       gdb_fread_le(fin, &xcolour, sizeof(xcolour), 32, "xcolour");
-       gdb_fread_le(fin, &count, sizeof(count), 32, "count");
+       gdb_fread_le(&xdisplay, sizeof(xdisplay), 8, prefix0, "display");
+       gdb_fread_le(&xcolour, sizeof(xcolour), 32, prefix0, "colour");
+       gdb_fread_le(&count, sizeof(count), 32, prefix0, "count");
 
        track = route_head_alloc();
        track->rte_name = xstrdup(xname);
        track_add_head(track);
        
-       while (count > 0
+       while (count--
        {
-           count--;
-           
-           gdb_fread_le(fin, &xlat, sizeof(xlat), 32, "xlat");
-           gdb_fread_le(fin, &xlon, sizeof(xlon), 32, "xlon");
+           gdb_fread_le(&xlat, sizeof(xlat), 32, prefix, "latitude");
+           gdb_fread_le(&xlon, sizeof(xlon), 32, prefix, "longitude");
            
-           gdb_fread(buff, 1, 1, fin);                                 /* altitude flag */
+           gdb_fread(buff, 1);                                         /* altitude flag */
            if (buff[0] == 1)
-               gdb_fread_le(fin, &xalt, sizeof(xalt), 64, "xalt");
+               gdb_fread_le(&xalt, sizeof(xalt), 64, prefix, "altitude");
            
-           gdb_fread(buff, 1, 1, fin);                                 /* date/time flag */
+           gdb_fread(buff, 1);                                         /* date/time flag */
            if (buff[0] == 1)
-               gdb_fread_le(fin, &xtime, sizeof(xtime), 32, "xtime");
+               gdb_fread_le(&xtime, sizeof(xtime), 32, prefix, "time");
                    
-           gdb_fread(buff, 1, 1, fin);                                 /* depth flag */
+           gdb_fread(buff, 1);                                         /* depth flag */
            if (buff[0] == 1)
-               gdb_fread_le(fin, &xdepth, sizeof(xdepth), 64, "xdepth");
+               gdb_fread_le(&xdepth, sizeof(xdepth), 64, prefix, "depth");
            
-           gdb_fread(buff, 1, 1, fin);
+           gdb_fread(buff, 1);                                         /* temperature flag */
            if (buff[0] == 1)
-               gdb_fread_le(fin, &xtemp, sizeof(xtemp), 64, "xtemp");
+               gdb_fread_le(&xtemp, sizeof(xtemp), 64, prefix, "temperature");
            
            wpt = waypt_new();
            
@@ -728,98 +849,828 @@ gdb_read_track(const size_t max_file_pos)
            wpt->altitude = xalt;
            wpt->depth = xdepth;
            
-           gdb_is_valid(fabs(wpt->latitude) <= 90.0 && fabs(wpt->longitude) <= 180.0, " - trk read loop: invalid lat or lon");
+           gdb_is_validf(fabs(wpt->latitude) <= 90.0, prefix, "Invalid latitude (%f)", wpt->latitude);
            
            route_add_wpt(track, wpt);
        }
        
+       gdb_fread(buff, 1);
+       
        return track;
 }
 
+/*******************************************************************************/
 
-static void
+void
 gdb_read_data(void)
 {
-       int reclen, done;
+       int reclen, warnings;
        char typ;
-       size_t curpos, deltapos;
-       waypoint *wpt;
+       size_t curpos, anchor;
        int wptclass;
        
-       done = 0;
-       while (!feof(fin) && (done == 0))
-       {
+       const char *prefix = "main_read_loop";
+
+       gdb_hidden = route_head_alloc();
+       track_add_head(gdb_hidden);
+
+       warnings = 0;
+       
+       anchor = ftell(fin);
 
-           gdb_fread_le(fin, &reclen, sizeof(reclen), 32, "reclen");
-           gdb_is_valid(reclen > 0 && reclen < 0x1F00000, "gdb data loop");
-           gdb_fread(&typ, 1, 1, fin);
+       /* we go twice through the file to keep sure, all waypoints 
+          are loaded before any route has to be handled */
+       
+       while (feof(fin) == 0)
+       {
+           
+           gdb_fread_le(&reclen, sizeof(reclen), 32, prefix, "record length");
+           gdb_is_valid(reclen > 0 && reclen < 0x1F00000, prefix, "record length");
+           gdb_fread(&typ, 1);
            
            curpos = ftell(fin);
            
-           switch(typ)
+           if (typ == 'W')
            {
-               case 'W':
-                   wpt = gdb_read_wpt(curpos + reclen, &wptclass);
-                   if (wpt != NULL )
+               int delta;
+               waypoint *wpt;
+               
+               wpt = gdb_read_wpt(curpos + reclen, &wptclass);
+               if (wpt != NULL )
+               {
+                   if (wptclass == 0)
+                       waypt_add(wpt);
+                   else if (gdb_via == 0)
+                       route_add_wpt(gdb_hidden, wpt);
+                   else
+                       waypt_free(wpt);
+               }
+               delta = (int)((curpos + reclen) - ftell(fin));
+               if (delta != 0)
+               {
+                   if ((warnings & 1) == 0)
                    {
-                       if (wptclass == 0)
-                           waypt_add(wpt);
-                       else
-                           route_add_wpt(gdb_hidden, wpt);
+                       warnings |= 1;
+                       warning(MYNAME "-%s: At least one incomplete waypoint read (%d byte(s) left).\n", prefix, delta);
                    }
-                   deltapos = (curpos+reclen)-ftell(fin);
-                   break;
-               case 'T':
-                   gdb_read_track(curpos + reclen);
-                   break;
-               case 'R':
-                   gdb_read_route();
-                   break;
-               case 'L':
-                   break;
-               case 'V':
-                   done = 1;
-                   break;
-               default:
-                   printf(MYNAME ": found unknown record type \"%c\"!\n", typ);
+                   fseek(fin, curpos + reclen, SEEK_SET);
+               }
+               continue;
            }
+           else if (typ == 'V')
+               break;
+               
            fseek(fin, curpos + reclen, SEEK_SET);
        }
+
+       clearerr(fin);
+       fseek(fin, anchor, SEEK_SET);
+
+       while (feof(fin) == 0)
+       {
+           gdb_fread_le(&reclen, sizeof(reclen), 32, prefix, "record length");
+           gdb_is_valid(reclen > 0 && reclen < 0x1F00000, prefix, "record length");
+           gdb_fread(&typ, 1);
+           
+           curpos = ftell(fin);
+           
+           if ((typ == 'R') || (typ == 'T'))
+           {
+               int flag, delta;
+               
+               if (typ == 'R')
+               {
+                   gdb_read_route();
+                   flag = 2; 
+               }
+               else
+               {
+                   gdb_read_track(curpos + reclen); 
+                   flag = 4;
+               }
+               delta = (int)((curpos + reclen) - ftell(fin));
+               if (delta != 0)
+               {
+                   if ((delta != reclen) && ((warnings & flag) == 0))
+                   {
+                       warnings |= flag;
+                       warning(MYNAME "-%s: At least one incomplete %s (gdb v%d.0, %d byte(s) left).\n", 
+                           prefix, (typ == 'R') ? "route" : "track", gdb_ver, delta);
+                   }
+                   fseek(fin, curpos + reclen, SEEK_SET);
+               }
+           }
+           else 
+           {
+               if (typ == 'V') break;
+               
+               switch(typ)
+               {
+                   case 'D': break;
+                   case 'L': break;
+                   case 'W': break;
+                   default: warning(MYNAME "-%s: Found unknown record type \"%c\"!\n", prefix, typ);
+               }
+               fseek(fin, curpos + reclen, SEEK_SET);
+           }
+       }
+       
+       /* finally kill our temporary queue */
+       track_del_head(gdb_hidden);
+}
+
+/*******************************************************************************/
+/* %%%                         write support                               %%% */
+/*******************************************************************************/
+
+/* helpers */
+
+waypoint **
+gdb_route_point_list(const route_head *route, int *count)
+{
+       waypoint **result;
+       queue *elem, *tmp;
+       int i = 0;
+       
+       QUEUE_FOR_EACH((queue *)&route->waypoint_list, elem, tmp)
+       {
+           waypoint *wpt = (waypoint *)elem;
+           if ((gdb_via == 0) || 
+               (gdb_detect_rtept_class(wpt) == GDB_DEFAULTWPTCLASS)) i++;
+       }
+       
+       *count = i;
+       if (i == 0) return NULL;
+       
+       result = xcalloc(i, sizeof(*result));
+
+       i = 0;
+       QUEUE_FOR_EACH((queue *)&route->waypoint_list, elem, tmp)
+       {
+           waypoint *wpt = (waypoint *)elem;
+           if ((gdb_via == 0) || 
+               (gdb_detect_rtept_class(wpt) == GDB_DEFAULTWPTCLASS)) 
+           result[i++] = wpt;
+       }
+       
+       return result;
+}
+
+void 
+gdb_fwrite(const void *data, const size_t size)
+{
+       fwrite(data, size, 1, fout);
+}
+
+void 
+gdb_fwrite_str(const char *str, const int len)
+{
+
+       if (len >= 0)                   
+           gdb_fwrite(str, len);       /* write a string with fixed length */
+       else
+       {
+           char *tmp = str_utf8_to_cp1252((str != NULL) ? str : "");
+           gdb_fwrite(tmp, strlen(tmp) + 1);
+           xfree(tmp);
+       }
+}
+
+void 
+gdb_fwrite_le(const void *data, const size_t size)
+{
+       int i;
+       short s;
+       char buff[8];
+       
+       switch(size)
+       {
+           case 1:
+               gdb_fwrite(data, 1);
+               break;
+               
+           case 2:             /* sizeof(short): */
+               s = *(short *)data;
+               le_write16(&s, s);
+               gdb_fwrite(&s, 2);
+               break;
+               
+           case 4:             /* sizeof(int): */
+               i = *(int *)data;
+               le_write32(&i, i);
+               gdb_fwrite(&i, 4);
+               break;
+
+           case 8:             /* sizeof(double): */
+               le_read64(buff, data);
+               gdb_fwrite(buff, 8);
+               break;
+               
+           default:
+               fatal(MYNAME "-write_le: Unsupported data size (%ld)!\n", size);
+       }
+}
+
+void
+gdb_fwrite_alt(const double alt, const double unknown_value)
+{
+       char c0 = 0;
+       char c1 = 1;
+       
+       if (alt != unknown_value)       /* proximity / depth / altitude */
+       {
+           gdb_fwrite(&c1, 1);
+           gdb_fwrite_le(&alt, sizeof(alt));
+       }
+       else
+           gdb_fwrite(&c0, 1);         /* no value */
+}
+
+void 
+gdb_fwrite_int(const int data)
+{
+       gdb_fwrite_le(&data, sizeof(data));
+}
+
+void 
+gdb_fwrite_icon(const waypoint *wpt)   /* partly taken from mapsource.c */
+{
+       int icon;
+       char buff[128];
+       
+       if (    /* handle custom icons, which are linked to -2 in garmin_tables.c */
+           (wpt->icon_descr != NULL) && 
+           (sscanf(wpt->icon_descr, "%s%d", buff, &icon) == 2) &&
+           (case_ignore_strcmp(buff, "Custom") == 0) &&
+           (icon >= 0) && (icon <= 63)
+          ) 
+       {
+           icon += 500;
+       }
+       else
+       {
+           /* might need to change this to handle version dependent icon handling */
+           icon = gdb_find_icon_number_from_desc(wpt->icon_descr, MAPSOURCE);
+           if (get_cache_icon(wpt) /* && wpt->icon_descr && (strcmp(wpt->icon_descr, "Geocache Found") != 0)*/) 
+           {
+               icon = gdb_find_icon_number_from_desc(get_cache_icon(wpt), MAPSOURCE);
+           }
+       }
+       gdb_fwrite_le(&icon, sizeof(icon));
+}
+
+/*******************************************************************************/
+/* %%%                       write file header                             %%% */
+/*-----------------------------------------------------------------------------*/
+
+void
+gdb_write_file_header(const struct tm *tm)
+{
+       char buff[128];
+       char *c;
+       int len;
+       
+       gdb_fwrite_str("MsRcf", -1);
+       gdb_fwrite_int(2);
+       
+       strncpy(buff, "Dx", sizeof(buff));
+       buff[1] = 'k' - 1 + gdb_ver;
+       gdb_fwrite_str(buff, -1);
+       
+#if 0
+       strncpy(buff, "A].SQA*Dec 27 2004*17:40:51", sizeof(buff));             /* MapSource V6.5 */
+#else
+       /* This is our "Watermark" to show this file was not created by MapSource */
+       /* !!! We should define the date use through Makefile !!! */
+       strncpy(buff, "A].GPSBabel*Jul 29 2005*09:52:51", sizeof(buff));        /* gpsbabel V1.2.6 */
+#endif
+       len = strlen(buff);
+       buff[2] = 2;
+
+       c = buff;       
+       while ((c = strchr(c, '*'))) *c++ = '\0';
+
+       gdb_fwrite_int(len);
+       gdb_fwrite_str(buff, len + 1);
+
+       gdb_fwrite_str("MapSource", -1);                        /* MapSource magic */
+}
+
+/*******************************************************************************/
+/* %%%                         write waypoints                             %%% */
+/*-----------------------------------------------------------------------------*/
+
+void 
+gdb_write_waypt(const waypoint *wpt, const int hidden)
+{
+       int i;
+       char ffbuf[32], zbuf[32];
+       char c0 = 0;
+       char c1 = 1;
+       
+       gdb_is_validf((fabs(wpt->latitude) <= 90), "wpt_write", 
+           "%s: Invalid latitude (%f) detected\n", wpt->shortname, wpt->latitude);
+
+       memset(ffbuf, 0xFF, sizeof(ffbuf));
+       memset(zbuf, 0x00, sizeof(zbuf));
+       
+       gdb_fwrite_str(wpt->shortname, -1);
+
+       gdb_fwrite_int( (hidden != 0) ? 
+           GDB_HIDDENROUTEWPTCLASS : GDB_DEFAULTWPTCLASS); /* class */
+       gdb_fwrite_str("", -1);                         /* country */
+
+       gdb_fwrite(zbuf, 4);                            /* subclass part 1 */
+       gdb_fwrite(ffbuf, 12);                          /* subclass part 2 */
+       gdb_fwrite(zbuf, 2);                            /* subclass part 3 */
+       gdb_fwrite(ffbuf, 4);                           /* unknown */
+
+       gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->latitude));
+       gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->longitude));
+       
+       gdb_fwrite_alt(wpt->altitude, unknown_alt);     /* altitude */
+       gdb_fwrite_str(wpt->description, -1);           /* description */
+       gdb_fwrite_alt(wpt->proximity, unknown_alt);    /* proximity */
+       
+#if 0
+       gdb_fwrite_int((wpt->garmin_data != NULL) ? wpt->garmin_data->display : 0);     /* display */
+       gdb_fwrite_int((wpt->garmin_data != NULL) ? wpt->garmin_data->colour : 0);      /* colour */
+#else
+       gdb_fwrite_int(0);                                                              /* display */
+       gdb_fwrite_int(0);                                                              /* colour */
+#endif
+       gdb_fwrite_icon(wpt);                           /* icon    */   
+       gdb_fwrite_str("", -1);                         /* city */
+       gdb_fwrite_str("", -1);                         /* state */
+       gdb_fwrite_str("", -1);                         /* facility */
+       gdb_fwrite(zbuf, 1);                            /* unknown */
+       gdb_fwrite_alt(wpt->depth, unknown_alt);        /* depth */
+
+       gdb_fwrite(zbuf, 3);                            /* three unknown bytes */
+       gdb_fwrite(zbuf, 4);                            /* four unknown bytes */
+
+       gdb_fwrite_str(wpt->notes, -1);                 /* notes */
+
+#if 0
+       if (gdb_opt_category != NULL)                   /* category */
+           i = gdb_category;
+       else
+           i = (wpt->garmin_data != NULL) ? wpt->garmin_data->category : 0;
+#else
+       i = gdb_category;
+#endif
+       gdb_fwrite_le(&i, 2);
+
+       gdb_fwrite(zbuf, 1);                            /* temperature flag */
+       
+       if (wpt->creation_time != 0)                    /* creation time */
+       {
+           gdb_fwrite(&c1, 1);
+           gdb_fwrite_int(wpt->creation_time);
+       }
+       else 
+           gdb_fwrite(&c0, 1);
+
+}
+
+static void 
+gdb_write_waypt_cb(const waypoint *wpt)                        /* called by waypt_disp over all waypoints */
+{
+       int reclen;
+       size_t pos;
+       
+       /* check for duplicate waypoints */
+       if (NULL != gdb_find_wpt_q_by_name((queue *)&gdb_hidden->waypoint_list, wpt->shortname))
+           return;
+
+       gdb_fwrite_int(0);
+       gdb_fwrite_str("W", 1);
+       
+       pos = ftell(fout);
+       gdb_write_waypt(wpt, 0);
+       reclen = ftell(fout) - pos;
+       
+       fseek(fout, pos - 5, SEEK_SET);
+       gdb_fwrite_int(reclen);
+       
+       fseek(fout, pos + reclen, SEEK_SET);
+
+       route_add_wpt(gdb_hidden, waypt_dupe(wpt));     /* add tis point to our internal queue */
+}
+
+static void
+gdb_write_rtewpt_cb(const waypoint *wpt)               /* called by waypt_disp (route points) */
+{
+       int reclen;
+       size_t pos;
+       waypoint *tmp;
+
+       tmp = gdb_find_wpt_q_by_name((queue *)&gdb_hidden->waypoint_list, wpt->shortname);
+       if (tmp == NULL)
+       {
+           tmp = find_waypt_by_name(wpt->shortname);
+           
+           gdb_fwrite_int(0);
+           gdb_fwrite_str("W", 1);
+       
+           pos = ftell(fout);
+           gdb_write_waypt(wpt, (tmp == NULL));
+           reclen = ftell(fout) - pos;
+       
+           fseek(fout, pos - 5, SEEK_SET);
+           gdb_fwrite_int(reclen);
+       
+           fseek(fout, pos + reclen, SEEK_SET);
+
+           route_add_wpt(gdb_hidden, waypt_dupe(wpt)); /* add tis point to our internal queue */
+       }
 }
 
-/* %%% gobal callbacks %%% */
+/*******************************************************************************/
+/* %%%                         write routes                                %%% */
+/*-----------------------------------------------------------------------------*/
 
-static void gdb_rd_init(const char *fname)
+void
+gdb_write_route(const route_head *route, const waypoint **list, const int count)
 {
+       int i, wpt_class;
+       char buff[128], zbuff[32], ffbuff[32];
+       waypoint *prev = NULL;
+       const char c0 = 0;
+       const char c1 = 1;
+       const char c3 = 3;
+       double maxlat = -90;
+       double minlat = +90;
+       double maxlon = -180;
+       double minlon = +180;
+       double maxalt = -unknown_alt;
+       double minalt = +unknown_alt;
+
+       memset(zbuff, 0, sizeof(zbuff));
+       memset(ffbuff, 0xFF, sizeof(ffbuff));
+               
+       for (i = 0; i < count; i++)
+       {
+           const waypoint *wpt = list[i];
+           
+           if (wpt->latitude > maxlat) maxlat = wpt->latitude;
+           if (wpt->latitude < minlat) minlat = wpt->latitude;
+           if (wpt->longitude > maxlon) maxlon = wpt->longitude;
+           if (wpt->longitude < minlon) minlon = wpt->longitude;
+           if (wpt->altitude != unknown_alt)
+           {
+               if (wpt->altitude > maxalt) maxalt = wpt->altitude;
+               if (wpt->altitude < minalt) minalt = wpt->altitude;
+           }
+       }
+
+       if (route->rte_name == NULL)
+       {
+           snprintf(buff, sizeof(buff), "Route%04d", route->rte_num);
+           gdb_fwrite_str(buff, -1);
+       }
+       else
+           gdb_fwrite_str(route->rte_name, -1);
+
+       gdb_fwrite(&c0, 1);                                     /* auto_name */
+       
+       if (count == 1) gdb_fwrite(&c1, 1);                     /* skip max data */
+       else
+       {       
+           gdb_fwrite(&c0, 1);                                 /* ??? */
+           gdb_fwrite_int(GPS_Math_Deg_To_Semi(maxlat));       /* maximum latitude over route */
+           gdb_fwrite_int(GPS_Math_Deg_To_Semi(maxlon));       /* maximum longitude over route */
+           gdb_fwrite_alt(maxalt, unknown_alt);                /* maximum altitude over route */
+
+           gdb_fwrite_int(GPS_Math_Deg_To_Semi(minlat));       /* minimum latitude over route */
+           gdb_fwrite_int(GPS_Math_Deg_To_Semi(minlon));       /* minimum longitude over route */
+           gdb_fwrite_alt(minalt, -unknown_alt);               /* minimum altitude over route */
+       }
+
+       gdb_fwrite_int(count);                                  /* number of points in route */ 
+       
+       for (i = 0; i < count; i++)
+       {
+           const waypoint *wpt = list[i];
+
+           wpt_class = gdb_detect_rtept_class(wpt);
+           
+           if (prev != NULL)
+           {
+               gdb_fwrite_int(2);                                      /* route link details */
+
+               gdb_fwrite_int(GPS_Math_Deg_To_Semi(prev->latitude));   /* ilink step 1 (end point 1) */
+               gdb_fwrite_int(GPS_Math_Deg_To_Semi(prev->longitude));
+               gdb_fwrite_alt(prev->altitude, unknown_alt);
+
+               gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->latitude));    /* ilink step 2 (end point 2) */
+               gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->longitude));
+               gdb_fwrite_alt(wpt->altitude, unknown_alt);
+               
+               if (wpt->latitude > prev->latitude)                     /* get maximum lat, lon and alt */
+               {
+                   maxlat = wpt->latitude;
+                   minlat = prev->latitude;
+               }
+               else
+               {
+                   maxlat = prev->latitude;
+                   minlat = wpt->latitude;
+               }
+               if (wpt->longitude > prev->longitude)
+               {
+                   maxlon = wpt->longitude;
+                   minlon = prev->longitude;
+               }
+               else
+               {
+                   maxlon = prev->longitude;
+                   minlon = wpt->longitude;
+               }
+               if (wpt->altitude != unknown_alt)
+               {
+                   maxalt = wpt->altitude;
+                   minalt = wpt->altitude;
+               }
+               else
+               {
+                   maxalt = -unknown_alt;
+                   minalt = +unknown_alt;
+               }
+               if (prev->altitude != unknown_alt)
+               {
+                   if (prev->altitude > maxalt) maxalt = prev->altitude;
+                   if (prev->altitude < minalt) minalt = prev->altitude;
+               }
+               
+               gdb_fwrite(&c0, 1);                                     /* ??? */
+               
+               gdb_fwrite_int(GPS_Math_Deg_To_Semi(maxlat));           /* maximum coords & altitude  */
+               gdb_fwrite_int(GPS_Math_Deg_To_Semi(maxlon));
+               gdb_fwrite_alt(maxalt, unknown_alt);
+
+               gdb_fwrite_int(GPS_Math_Deg_To_Semi(minlat));           /* minimum coords & altitude */
+               gdb_fwrite_int(GPS_Math_Deg_To_Semi(minlon));
+               gdb_fwrite_alt(minalt, -unknown_alt);
+
+               if (gdb_ver > 1)
+                   gdb_fwrite(ffbuff, 8);
+           }
+           
+           gdb_fwrite_str(wpt->shortname, -1);                         /* short name */
+           
+           gdb_fwrite_int(wpt_class);                                  /* class */
+           gdb_fwrite_str("", -1);                                     /* country */
+           
+           gdb_fwrite(zbuff, 4);                                       /* subclass part 1 */
+           gdb_fwrite(ffbuff, 12);                                     /* subclass part 2 */
+           gdb_fwrite(zbuff, 2);                                       /* subclass part 3 */
+           gdb_fwrite(ffbuff, 4);                                      /* unknown */
+           
+           gdb_fwrite(&c0, 1);                                 /* unknown value or string */
+           gdb_fwrite(&c3, 1);                                 /* unknown 18 bytes starting with 0x03 */
+           gdb_fwrite(zbuff, 3);
+           gdb_fwrite(ffbuff, 4);
+           gdb_fwrite(zbuff, 10);
+           
+           prev = (waypoint *)wpt;
+       }
+       
+       gdb_fwrite_int(0);              /* Zero interlink steps */
+       gdb_fwrite(&c1, 1);
+
+       if (gdb_ver > 1)
+           gdb_fwrite(ffbuff, 8);
+           
+       gdb_fwrite(&c0, 1);
+}
+
+static void
+gdb_write_route_cb(const route_head *route)
+{
+       int reclen;
+       size_t pos;
+       int count;
+       waypoint **list;
+       
+       list = gdb_route_point_list(route, &count);
+       if (count == 0) return;                                         /* don't write empty routes */
+
+       gdb_fwrite_int(0);
+       gdb_fwrite_str("R", 1);
+       
+       pos = ftell(fout);
+       gdb_write_route(route, (const waypoint**)list, count);
+       reclen = ftell(fout) - pos;
+       
+       fseek(fout, pos - 5, SEEK_SET);
+       gdb_fwrite_int(reclen);
+       
+       fseek(fout, pos + reclen, SEEK_SET);
+       
+       xfree(list);
+}
+
+/*******************************************************************************/
+/* %%%                          write tracks                               %%% */
+/*-----------------------------------------------------------------------------*/
+
+void 
+gdb_write_track(const route_head *track)
+{
+       char buff[128];
+       const char c0 = 0;
+       const char c1 = 1;
+       queue *elem, *tmp;
+       int count = track->rte_waypt_ct;
+       
+       if (track->rte_name == NULL)
+           snprintf(buff, sizeof(buff), "Track%04d", track->rte_num);
+       else 
+           strncpy(buff, track->rte_name, sizeof(buff));
+           
+       gdb_fwrite_str(buff, -1);
+       gdb_fwrite(&c0, 1);                             /* display */
+       gdb_fwrite_int(0);                              /* xcolour */
+       gdb_fwrite_int(count);
+       
+       QUEUE_FOR_EACH((queue *)&track->waypoint_list, elem, tmp)
+       {
+           waypoint *wpt = (waypoint *)elem;
+           
+           gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->latitude));
+           gdb_fwrite_int(GPS_Math_Deg_To_Semi(wpt->longitude));
+           gdb_fwrite_alt(wpt->altitude, unknown_alt); /* altitude */
+           
+
+           if (wpt->creation_time != 0)                        /* creation time */
+           {
+               gdb_fwrite(&c1, 1);
+               gdb_fwrite_int(wpt->creation_time);
+           }
+           else 
+               gdb_fwrite(&c0, 1);
+                   
+           gdb_fwrite_alt(wpt->depth, unknown_alt);    /* depth */
+           gdb_fwrite(&c0, 1);                         /* temperature */
+       }
+       gdb_fwrite(&c0, 1);
+}
+
+static void
+gdb_write_track_cb(const route_head *track)                    /* called from track_disp_all */
+{
+       int reclen;
+       size_t pos;
+       
+       if (track->rte_waypt_ct <= 0) return;                   /* don't write empty tracks */
+       
+       gdb_fwrite_int(0);
+       gdb_fwrite_str("T", 1);
+       
+       pos = ftell(fout);
+       
+       gdb_write_track(track);
+       
+       reclen = ftell(fout) - pos;
+       fseek(fout, pos - 5, SEEK_SET);
+       gdb_fwrite_int(reclen);
+       
+       fseek(fout, pos + reclen, SEEK_SET);
+}
+
+/*******************************************************************************/
+
+void
+gdb_write_data(void)
+{
+       char c1 = 1;
+
+       gdb_hidden = route_head_alloc();        /* contains all written waypts & rtepts */
+       track_add_head(gdb_hidden);             /* tracks comes later and we drop this before */
+
+       if (doing_wpts) waypt_disp_all(gdb_write_waypt_cb);
+       if (doing_rtes)
+       {
+           
+           if (gdb_via == 0) 
+           {
+               /* find out all route points we have to write as a "HIDDEN CLASS" waypoint */
+               route_disp_all(NULL, NULL, gdb_write_rtewpt_cb);
+           }
+           route_disp_all(gdb_write_route_cb, NULL, NULL);
+       }
+
+       track_del_head(gdb_hidden);             /* vaporize our temporary queue */
+
+       if (doing_trks) track_disp_all(gdb_write_track_cb, NULL, NULL);
+
+       gdb_fwrite_int(2);                      /* finalize gdb with empty map segment */
+       gdb_fwrite_str("V", -1);
+       gdb_fwrite(&c1, 1);
+}
+
+/*******************************************************************************/
+
+void
+gdb_init_opts(const char op)   /* 1 = read; 2 = write */
+{
+       gdb_via = 0;
+       gdb_category = 0;
+       gdb_ver = 2;
+       
+       if (gdb_opt_via != NULL)        /* opt_via present in both ops */
+       {
+           if ((case_ignore_strcmp(gdb_opt_via, GDB_OPT_VIA) == 0) ||
+               (*gdb_opt_via == '\0'))
+               gdb_via = 1;
+           else
+               gdb_via = atoi(gdb_opt_via);
+       }
+       
+       if (op & 2)             /* writer opts */
+       {
+           if ((gdb_opt_category != NULL) &&
+               (case_ignore_strcmp(gdb_opt_category, GDB_OPT_CATEGORY) != 0) &&
+               (*gdb_opt_category != '\0'))
+           {
+               gdb_category = atoi(gdb_opt_category);
+               if ((gdb_category < 1) || (gdb_category > 16))
+                   fatal(MYNAME ": Unsupported category \"%s\"!\n", gdb_opt_category);
+               gdb_category = 1 << --gdb_category;
+           }
+           
+           gdb_ver = atoi(gdb_opt_ver);
+           if ((gdb_ver < GDB_VER_MIN) || (gdb_ver > GDB_VER_MAX))
+               fatal(MYNAME ": Unsupported version \"%s\"!\n", gdb_opt_ver);
+       }
+}
+
+/*******************************************************************************/
+/* %%% global cb's %%% */
+/*******************************************************************************/
+
+static void 
+gdb_rd_init(const char *fname)
+{
+       gdb_init_opts(1);
+       
        fin_name = xstrdup(fname);
        fin = xfopen(fname, "rb", MYNAME);
-       gdb_hidden = route_head_alloc();
-       track_add_head(gdb_hidden);
 }
 
-static void gdb_rd_deinit(void)
+static void
+gdb_wr_init(const char *fname)
+{
+       gdb_init_opts(2);
+       
+       fout_name = xstrdup(fname);
+       fout = xfopen(fname, "wb", MYNAME);
+}
+
+static void 
+gdb_rd_deinit(void)
 {
-       track_del_head(gdb_hidden);
        fclose(fin);
        xfree(fin_name);
+       fin_name = NULL;
+}
+
+static void
+gdb_wr_deinit(void)
+{
+       fclose(fout);
+       xfree(fout_name);
+       fout_name = NULL;
 }
 
-static void gdb_read(void)
+static void 
+gdb_read(void)
 {
        gdb_read_file_header();
        gdb_read_data();
 }
 
+static void
+gdb_write(void)
+{
+       gdb_write_file_header(NULL);
+       gdb_write_data();
+}
+
+/*******************************************************************************/
 
 ff_vecs_t gdb_vecs = {
        ff_type_file,
-       { ff_cap_read, ff_cap_read, ff_cap_read },      /* FF_CAP_RW_ALL, !!! I hope !!! */
+       FF_CAP_RW_ALL,
        gdb_rd_init,    
-       NULL,           /* gdb_wr_init, */
+       gdb_wr_init,
        gdb_rd_deinit,
-       NULL,           /* gdb_wr_deinit, */
+       gdb_wr_deinit,
        gdb_read,
-       NULL,           /* gdb_write, */
+       gdb_write,
        NULL, 
-       NULL            /* gdb_args */
+       gdb_args
 };
+
+/*******************************************************************************/
index 06e1f726be133a8c5495c6b87aa2495ff15eed11..b848b77425eb65beb533804685cc6ee07942985f 100644 (file)
@@ -79,16 +79,26 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/
     <sym>Residence</sym>
   </rtept>
   <rtept lat="50.492606163" lon="12.105431557">
+<time>2005-04-26T14:27:21Z</time>
     <name>416</name>
+    <desc>Fahren Sie auf die Luis-Ferdinand-Sch&#xf6;nherr-Strasse nach Norden</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.492606163" lon="12.105431557">
+<time>2005-04-26T14:27:21Z</time>
     <name>417</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.494279861" lon="12.105131149">
+<time>2005-04-26T14:27:21Z</time>
     <name>418</name>
+    <desc>Biegen Sie rechts ab auf die Liebknechtstrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.493836962" lon="12.106101271">
+<time>2005-04-26T14:27:21Z</time>
     <name>419</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.493837046" lon="12.106101019">
 <time>2005-02-26T09:03:15Z</time>
@@ -98,13 +108,21 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/
     <sym>Golf Course</sym>
   </rtept>
   <rtept lat="50.493836962" lon="12.106101271">
+<time>2005-04-26T14:27:21Z</time>
     <name>420</name>
+    <desc>Fahren Sie auf die Liebknechtstrasse nach S&#xfc;dosten</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.493378639" lon="12.107105255">
+<time>2005-04-26T14:27:21Z</time>
     <name>421</name>
+    <desc>Biegen Sie links ab auf die Jahnstrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.493662786" lon="12.107152529">
+<time>2005-04-26T14:27:21Z</time>
     <name>422</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.493662870" lon="12.107152529">
 <time>2005-02-26T09:02:20Z</time>
@@ -114,112 +132,195 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/
     <sym>Golf Course</sym>
   </rtept>
   <rtept lat="50.493662786" lon="12.107152529">
+<time>2005-04-26T14:27:21Z</time>
     <name>423</name>
+    <desc>Fahren Sie auf die Jahnstrasse nach Norden</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.494666100" lon="12.107319832">
+<time>2005-04-26T14:27:21Z</time>
     <name>424</name>
+    <desc>Biegen Sie links ab auf die Neundorfer Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.494666100" lon="12.106633186">
+<time>2005-04-26T14:27:21Z</time>
     <name>425</name>
+    <desc>Biegen Sie rechts ab auf die Scharnhorststrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.496554375" lon="12.105002403">
+<time>2005-04-26T14:27:21Z</time>
     <name>426</name>
+    <desc>Biegen Sie rechts ab auf die Schminckestrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.497756004" lon="12.106332779">
+<time>2005-04-26T14:27:21Z</time>
     <name>427</name>
+    <desc>Biegen Sie links ab auf die Kopernikusstrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.499987602" lon="12.103672028">
+<time>2005-04-26T14:27:21Z</time>
     <name>428</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.499987602" lon="12.103672028">
+<time>2005-04-26T14:27:21Z</time>
     <name>429</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.500202179" lon="12.103500366">
+<time>2005-04-26T14:27:21Z</time>
     <name>430</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.502090454" lon="12.102470398">
+<time>2005-04-26T14:27:21Z</time>
     <name>431</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.503549576" lon="12.099037170">
+<time>2005-04-26T14:27:21Z</time>
     <name>432</name>
+    <desc>Ordnen Sie sich rechts ein in Richtung Talstrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.510201454" lon="12.092342377">
+<time>2005-04-26T14:27:21Z</time>
     <name>433</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.512003899" lon="12.090926170">
+<time>2005-04-26T14:27:21Z</time>
     <name>434</name>
+    <desc>Biegen Sie rechts ab auf die Zwoschwitzer Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.512475967" lon="12.091741562">
+<time>2005-04-26T14:27:21Z</time>
     <name>435</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.520200729" lon="12.091612816">
+<time>2005-04-26T14:27:21Z</time>
     <name>436</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.523333549" lon="12.092986107">
+<time>2005-04-26T14:27:21Z</time>
     <name>437</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.524277687" lon="12.093672752">
+<time>2005-04-26T14:27:21Z</time>
     <name>438</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.525264740" lon="12.093973160">
+<time>2005-04-26T14:27:21Z</time>
     <name>439</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.525865555" lon="12.094359398">
+<time>2005-04-26T14:27:21Z</time>
     <name>440</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.526509285" lon="12.094831467">
+<time>2005-04-26T14:27:21Z</time>
     <name>441</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.530071259" lon="12.098007202">
+<time>2005-04-26T14:27:21Z</time>
     <name>442</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.534362793" lon="12.104401588">
+<time>2005-04-26T14:27:21Z</time>
     <name>443</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.534491539" lon="12.104487419">
+<time>2005-04-26T14:27:21Z</time>
     <name>444</name>
+    <desc>Biegen Sie links ab auf die An Der Sch&#xf6;psdrehe</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.534920692" lon="12.103457451">
+<time>2005-04-26T14:27:21Z</time>
     <name>445</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.535736084" lon="12.100839615">
+<time>2005-04-26T14:27:21Z</time>
     <name>446</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.535778999" lon="12.100667953">
+<time>2005-04-26T14:27:21Z</time>
     <name>447</name>
+    <desc>Biegen Sie rechts ab auf die Elsterberger Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.537710190" lon="12.102599144">
+<time>2005-04-26T14:27:21Z</time>
     <name>448</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.544619560" lon="12.105388641">
+<time>2005-04-26T14:27:21Z</time>
     <name>449</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.591139793" lon="12.138476372">
+<time>2005-04-26T14:27:21Z</time>
     <name>450</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.591440201" lon="12.138905525">
+<time>2005-04-26T14:27:21Z</time>
     <name>451</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.605859756" lon="12.154955864">
+<time>2005-04-26T14:27:21Z</time>
     <name>452</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.605387688" lon="12.160363197">
+<time>2005-04-26T14:27:21Z</time>
     <name>453</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.607104301" lon="12.168259621">
+<time>2005-04-26T14:27:21Z</time>
     <name>454</name>
+    <desc>Biegen Sie rechts ab auf die Robert-Schenker-Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.606160164" lon="12.168302536">
+<time>2005-04-26T14:27:21Z</time>
     <name>455</name>
+    <desc>Biegen Sie links ab auf die Rosa-Luxemburg-Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.607061386" lon="12.172594070">
+<time>2005-04-26T14:27:21Z</time>
     <name>456</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.609421730" lon="12.175040245">
+<time>2005-04-26T14:27:21Z</time>
     <name>457</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.610795189" lon="12.173802238">
+<time>2005-04-26T14:27:21Z</time>
     <name>458</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.610795273" lon="12.173802154">
 <time>2005-02-26T08:59:59Z</time>
@@ -229,61 +330,104 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/
     <sym>Golf Course</sym>
   </rtept>
   <rtept lat="50.610795189" lon="12.173802238">
+<time>2005-04-26T14:27:22Z</time>
     <name>459</name>
+    <desc>Fahren Sie auf die Piehlerstrasse nach Nordwesten</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.612468719" lon="12.168731689">
+<time>2005-04-26T14:27:22Z</time>
     <name>460</name>
+    <desc>Biegen Sie rechts ab auf die Greizer Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.616717339" lon="12.170190811">
+<time>2005-04-26T14:27:22Z</time>
     <name>461</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.619249344" lon="12.172937393">
+<time>2005-04-26T14:27:22Z</time>
     <name>462</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.623326302" lon="12.176756859">
+<time>2005-04-26T14:27:22Z</time>
     <name>463</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.623583794" lon="12.180147171">
+<time>2005-04-26T14:27:22Z</time>
     <name>464</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.633797646" lon="12.192077637">
+<time>2005-04-26T14:27:22Z</time>
     <name>465</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.634012222" lon="12.192249298">
+<time>2005-04-26T14:27:22Z</time>
     <name>466</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.637145042" lon="12.191991806">
+<time>2005-04-26T14:27:22Z</time>
     <name>467</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.646672249" lon="12.195553780">
+<time>2005-04-26T14:27:22Z</time>
     <name>468</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.647916794" lon="12.194480896">
+<time>2005-04-26T14:27:22Z</time>
     <name>469</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.647959709" lon="12.194480896">
+<time>2005-04-26T14:27:22Z</time>
     <name>470</name>
+    <desc>Halten Sie sich rechts in Richtung Carolinenstrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.655169487" lon="12.198171616">
+<time>2005-04-26T14:27:22Z</time>
     <name>471</name>
+    <desc>Biegen Sie rechts ab auf die Gartenweg</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.654611588" lon="12.199459076">
+<time>2005-04-26T14:27:22Z</time>
     <name>472</name>
+    <desc>Biegen Sie links ab auf die  B94</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.655384064" lon="12.201776505">
+<time>2005-04-26T14:27:22Z</time>
     <name>473</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.655512810" lon="12.202463150">
+<time>2005-04-26T14:27:22Z</time>
     <name>474</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.655469894" lon="12.202720642">
+<time>2005-04-26T14:27:22Z</time>
     <name>475</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.654911995" lon="12.204480171">
+<time>2005-04-26T14:27:22Z</time>
     <name>476</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.654762965" lon="12.204956934">
+<time>2005-04-26T14:27:22Z</time>
     <name>477</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.654763049" lon="12.204956766">
 <time>2005-02-26T08:57:04Z</time>
@@ -293,142 +437,245 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/
     <sym>Golf Course</sym>
   </rtept>
   <rtept lat="50.654762965" lon="12.204956934">
+<time>2005-04-26T14:27:22Z</time>
     <name>478</name>
+    <desc>Fahren Sie auf die August-Bebel-Strasse nach S&#xfc;dosten</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.653924942" lon="12.207655907">
+<time>2005-04-26T14:27:22Z</time>
     <name>479</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.652594566" lon="12.211861610">
+<time>2005-04-26T14:27:22Z</time>
     <name>480</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.652036667" lon="12.227139473">
+<time>2005-04-26T14:27:22Z</time>
     <name>481</name>
+    <desc>Biegen Sie links ab auf die Werdauer Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.652594566" lon="12.227997780">
+<time>2005-04-26T14:27:22Z</time>
     <name>482</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.653667450" lon="12.231731415">
+<time>2005-04-26T14:27:22Z</time>
     <name>483</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.655684471" lon="12.242288589">
+<time>2005-04-26T14:27:22Z</time>
     <name>484</name>
+    <desc>Halten Sie sich rechts in Richtung Werdauer Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.656456947" lon="12.247138023">
+<time>2005-04-26T14:27:22Z</time>
     <name>485</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.657229424" lon="12.248253822">
+<time>2005-04-26T14:27:22Z</time>
     <name>486</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.668387413" lon="12.262930870">
+<time>2005-04-26T14:27:22Z</time>
     <name>487</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.671992302" lon="12.270097733">
+<time>2005-04-26T14:27:22Z</time>
     <name>488</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.675039291" lon="12.277135849">
+<time>2005-04-26T14:27:22Z</time>
     <name>489</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.675640106" lon="12.282586098">
+<time>2005-04-26T14:27:22Z</time>
     <name>490</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.675683022" lon="12.282757759">
+<time>2005-04-26T14:27:22Z</time>
     <name>491</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.678043365" lon="12.292113304">
+<time>2005-04-26T14:27:22Z</time>
     <name>492</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.684738159" lon="12.316360474">
+<time>2005-04-26T14:27:22Z</time>
     <name>493</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.695896149" lon="12.340135574">
+<time>2005-04-26T14:27:22Z</time>
     <name>494</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.697956085" lon="12.341938019">
+<time>2005-04-26T14:27:22Z</time>
     <name>495</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.698599815" lon="12.344083786">
+<time>2005-04-26T14:27:22Z</time>
     <name>496</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.698857307" lon="12.344899178">
+<time>2005-04-26T14:27:22Z</time>
     <name>497</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.706324577" lon="12.361764908">
+<time>2005-04-26T14:27:22Z</time>
     <name>498</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.714221001" lon="12.371807098">
+<time>2005-04-26T14:27:22Z</time>
     <name>499</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.714993477" lon="12.372364998">
+<time>2005-04-26T14:27:22Z</time>
     <name>500</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.716238022" lon="12.373266220">
+<time>2005-04-26T14:27:22Z</time>
     <name>501</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.724606514" lon="12.373137474">
+<time>2005-04-26T14:27:22Z</time>
     <name>502</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.728297234" lon="12.374081612">
+<time>2005-04-26T14:27:22Z</time>
     <name>503</name>
+    <desc>Halten Sie sich links in Richtung Marienstrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.731773376" lon="12.374167442">
+<time>2005-04-26T14:27:22Z</time>
     <name>504</name>
+    <desc>Biegen Sie links ab auf die Uferstrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.739798546" lon="12.376356125">
+<time>2005-04-26T14:27:22Z</time>
     <name>505</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.775847435" lon="12.368073463">
+<time>2005-04-26T14:27:22Z</time>
     <name>506</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.812239647" lon="12.388501167">
+<time>2005-04-26T14:27:22Z</time>
     <name>507</name>
+    <desc>Biegen Sie links ab auf die Querstrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.812325478" lon="12.387084961">
+<time>2005-04-26T14:27:22Z</time>
     <name>508</name>
+    <desc>Biegen Sie rechts ab auf die Carth&#xe4;userstrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.812454224" lon="12.386956215">
+<time>2005-04-26T14:27:22Z</time>
     <name>509</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.813097954" lon="12.386569977">
+<time>2005-04-26T14:27:22Z</time>
     <name>510</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.814642906" lon="12.385797501">
+<time>2005-04-26T14:27:22Z</time>
     <name>511</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.816531181" lon="12.385239601">
+<time>2005-04-26T14:27:22Z</time>
     <name>512</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.817217827" lon="12.385926247">
+<time>2005-04-26T14:27:22Z</time>
     <name>513</name>
+    <desc>Halten Sie sich links in Richtung S54</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.818977356" lon="12.385969162">
+<time>2005-04-26T14:27:22Z</time>
     <name>514</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.825457573" lon="12.387986183">
+<time>2005-04-26T14:27:22Z</time>
     <name>515</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.826058388" lon="12.388329506">
+<time>2005-04-26T14:27:22Z</time>
     <name>516</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.842709541" lon="12.393994331">
+<time>2005-04-26T14:27:22Z</time>
     <name>517</name>
+    <desc>Biegen Sie rechts ab auf die Leipziger Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.844254494" lon="12.397599220">
+<time>2005-04-26T14:27:22Z</time>
     <name>518</name>
+    <desc>Biegen Sie rechts ab auf die Leipziger Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.842108727" lon="12.400431633">
+<time>2005-04-26T14:27:22Z</time>
     <name>519</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.841979980" lon="12.400732040">
+<time>2005-04-26T14:27:22Z</time>
     <name>520</name>
+    <desc>Biegen Sie links ab auf die Ponitzer Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.843696594" lon="12.406182289">
+<time>2005-04-26T14:27:22Z</time>
     <name>521</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.843997002" lon="12.408328056">
+<time>2005-04-26T14:27:22Z</time>
     <name>522</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.844125664" lon="12.408756875">
+<time>2005-04-26T14:27:22Z</time>
     <name>523</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.844125748" lon="12.408757210">
 <time>2005-02-26T09:10:47Z</time>
@@ -438,34 +685,57 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/
     <sym>Golf Course</sym>
   </rtept>
   <rtept lat="50.844125664" lon="12.408756875">
+<time>2005-04-26T14:27:22Z</time>
     <name>524</name>
+    <desc>Fahren Sie auf die Gosel nach Nordosten</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.844254494" lon="12.409186363">
+<time>2005-04-26T14:27:22Z</time>
     <name>525</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.846185684" lon="12.412233353">
+<time>2005-04-26T14:27:22Z</time>
     <name>526</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.856056213" lon="12.423348427">
+<time>2005-04-26T14:27:22Z</time>
     <name>527</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.858330727" lon="12.424507141">
+<time>2005-04-26T14:27:22Z</time>
     <name>528</name>
+    <desc>Biegen Sie rechts ab auf die G&#xf6;ssnitzer Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.860562325" lon="12.427039146">
+<time>2005-04-26T14:27:22Z</time>
     <name>529</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.872192383" lon="12.434377670">
+<time>2005-04-26T14:27:22Z</time>
     <name>530</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.875239372" lon="12.435235977">
+<time>2005-04-26T14:27:22Z</time>
     <name>531</name>
+    <desc>Biegen Sie links ab auf die Altenburger Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.876870155" lon="12.434163094">
+<time>2005-04-26T14:27:22Z</time>
     <name>532</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.877340548" lon="12.433888670">
+<time>2005-04-26T14:27:22Z</time>
     <name>533</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.877340632" lon="12.433888670">
     <name>3</name>
@@ -474,76 +744,129 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/
     <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.877340548" lon="12.433888670">
+<time>2005-04-26T14:27:23Z</time>
     <name>534</name>
+    <desc>Fahren Sie auf die Altenburger Strasse nach Norden</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.879616737" lon="12.432918549">
+<time>2005-04-26T14:27:23Z</time>
     <name>535</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.880904198" lon="12.432188988">
+<time>2005-04-26T14:27:23Z</time>
     <name>536</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.881419182" lon="12.431759834">
+<time>2005-04-26T14:27:23Z</time>
     <name>537</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.887727737" lon="12.430858612">
+<time>2005-04-26T14:27:23Z</time>
     <name>538</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.888371468" lon="12.432703972">
+<time>2005-04-26T14:27:23Z</time>
     <name>539</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.888543129" lon="12.433948517">
+<time>2005-04-26T14:27:23Z</time>
     <name>540</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.901160240" lon="12.440814972">
+<time>2005-04-26T14:27:23Z</time>
     <name>541</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.902791023" lon="12.440428734">
+<time>2005-04-26T14:27:23Z</time>
     <name>542</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.905494690" lon="12.439956665">
+<time>2005-04-26T14:27:23Z</time>
     <name>543</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.910258293" lon="12.441716194">
+<time>2005-04-26T14:27:23Z</time>
     <name>544</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.911631584" lon="12.442531586">
+<time>2005-04-26T14:27:23Z</time>
     <name>545</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.920085907" lon="12.444977760">
+<time>2005-04-26T14:27:23Z</time>
     <name>546</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.924978256" lon="12.443475723">
+<time>2005-04-26T14:27:23Z</time>
     <name>547</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.933046341" lon="12.429485321">
+<time>2005-04-26T14:27:23Z</time>
     <name>548</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.935878754" lon="12.426309586">
+<time>2005-04-26T14:27:23Z</time>
     <name>549</name>
+    <desc>Biegen Sie links ab auf die Hauptstrasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.933132172" lon="12.420730591">
+<time>2005-04-26T14:27:23Z</time>
     <name>550</name>
+    <desc>Biegen Sie rechts ab auf die K61</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.933818817" lon="12.419013977">
+<time>2005-04-26T14:27:23Z</time>
     <name>551</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.938711166" lon="12.414765358">
+<time>2005-04-26T14:27:23Z</time>
     <name>552</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.941715240" lon="12.413306236">
+<time>2005-04-26T14:27:23Z</time>
     <name>553</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.942659378" lon="12.412362099">
+<time>2005-04-26T14:27:23Z</time>
     <name>554</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.949354172" lon="12.405452728">
+<time>2005-04-26T14:27:23Z</time>
     <name>555</name>
+    <desc>Biegen Sie rechts ab auf die Schm&#xf6;llner Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.956048965" lon="12.410302162">
+<time>2005-04-26T14:27:23Z</time>
     <name>556</name>
+    <desc>Halten Sie sich rechts in Richtung Stra&#xdf;e</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.964955157" lon="12.435919270">
+<time>2005-04-26T14:27:23Z</time>
     <name>557</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.964955240" lon="12.435919438">
 <time>2005-06-24T00:50:24Z</time>
@@ -553,148 +876,251 @@ xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/
     <sym>Golf Course</sym>
   </rtept>
   <rtept lat="50.964955157" lon="12.435919270">
+<time>2005-04-26T14:27:23Z</time>
     <name>558</name>
+    <desc>Fahren Sie auf die Stra&#xdf;e nach Nordosten</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.999994278" lon="12.470340729">
+<time>2005-04-26T14:27:23Z</time>
     <name>559</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="50.999994278" lon="12.470340729">
+<time>2005-04-26T14:27:23Z</time>
     <name>560</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.011323929" lon="12.454934120">
+<time>2005-04-26T14:27:23Z</time>
     <name>561</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.023340225" lon="12.456436157">
+<time>2005-04-26T14:27:23Z</time>
     <name>562</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.025185585" lon="12.457680702">
+<time>2005-04-26T14:27:23Z</time>
     <name>563</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.026730537" lon="12.458109856">
+<time>2005-04-26T14:27:23Z</time>
     <name>564</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.037459373" lon="12.458624840">
+<time>2005-04-26T14:27:23Z</time>
     <name>565</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.043510437" lon="12.455277443">
+<time>2005-04-26T14:27:23Z</time>
     <name>566</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.043682098" lon="12.455277443">
+<time>2005-04-26T14:27:23Z</time>
     <name>567</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.050333977" lon="12.454290390">
+<time>2005-04-26T14:27:23Z</time>
     <name>568</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.050977707" lon="12.454075813">
+<time>2005-04-26T14:27:23Z</time>
     <name>569</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.052565575" lon="12.453346252">
+<time>2005-04-26T14:27:23Z</time>
     <name>570</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.053166389" lon="12.453131676">
+<time>2005-04-26T14:27:23Z</time>
     <name>571</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.053895950" lon="12.453432083">
+<time>2005-04-26T14:27:23Z</time>
     <name>572</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.054925919" lon="12.453861237">
+<time>2005-04-26T14:27:23Z</time>
     <name>573</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.058444977" lon="12.454719543">
+<time>2005-04-26T14:27:23Z</time>
     <name>574</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.062393188" lon="12.454032898">
+<time>2005-04-26T14:27:23Z</time>
     <name>575</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.065225601" lon="12.453517914">
+<time>2005-04-26T14:27:23Z</time>
     <name>576</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.072306633" lon="12.460212708">
+<time>2005-04-26T14:27:23Z</time>
     <name>577</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.075139046" lon="12.463688850">
+<time>2005-04-26T14:27:23Z</time>
     <name>578</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.081104279" lon="12.465276718">
+<time>2005-04-26T14:27:23Z</time>
     <name>579</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.086254120" lon="12.468323708">
+<time>2005-04-26T14:27:23Z</time>
     <name>580</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.088700294" lon="12.469439507">
+<time>2005-04-26T14:27:23Z</time>
     <name>581</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.093463898" lon="12.473216057">
+<time>2005-04-26T14:27:23Z</time>
     <name>582</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.107110977" lon="12.489309311">
+<time>2005-04-26T14:27:23Z</time>
     <name>583</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.110973358" lon="12.490983009">
+<time>2005-04-26T14:27:23Z</time>
     <name>584</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.118955612" lon="12.484116554">
+<time>2005-04-26T14:27:23Z</time>
     <name>585</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.120371819" lon="12.485876083">
+<time>2005-04-26T14:27:23Z</time>
     <name>586</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.122260094" lon="12.489266396">
+<time>2005-04-26T14:27:23Z</time>
     <name>587</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.127624512" lon="12.504329681">
+<time>2005-04-26T14:27:23Z</time>
     <name>588</name>
+    <desc>Biegen Sie links ab auf die Leipziger Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.131916046" lon="12.505788803">
+<time>2005-04-26T14:27:23Z</time>
     <name>589</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.133460999" lon="12.506861687">
+<time>2005-04-26T14:27:23Z</time>
     <name>590</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.135735512" lon="12.508449554">
+<time>2005-04-26T14:27:23Z</time>
     <name>591</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.191182137" lon="12.470211983">
+<time>2005-04-26T14:27:23Z</time>
     <name>592</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.194314957" lon="12.462058067">
+<time>2005-04-26T14:27:23Z</time>
     <name>593</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.230278015" lon="12.388458252">
+<time>2005-04-26T14:27:23Z</time>
     <name>594</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.275467873" lon="12.383222580">
+<time>2005-04-26T14:27:23Z</time>
     <name>595</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.299843788" lon="12.376141548">
+<time>2005-04-26T14:27:23Z</time>
     <name>596</name>
+    <desc>Fahren Sie rechts ab auf die Prinz-Eugen-Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.301903725" lon="12.375884056">
+<time>2005-04-26T14:27:23Z</time>
     <name>597</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.302890778" lon="12.375154495">
+<time>2005-04-26T14:27:23Z</time>
     <name>598</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.303405762" lon="12.374296188">
+<time>2005-04-26T14:27:23Z</time>
     <name>599</name>
+    <desc>Biegen Sie rechts ab auf die Wolfgang-Heinze-Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.304135323" lon="12.374124527">
+<time>2005-04-26T14:27:23Z</time>
     <name>600</name>
+    <desc>Biegen Sie rechts ab auf die Meusdorfer Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.309285164" lon="12.387299538">
+<time>2005-04-26T14:27:23Z</time>
     <name>601</name>
+    <desc>Biegen Sie rechts ab auf die Arno-Nitzsche-Strasse</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.310272217" lon="12.396268845">
+<time>2005-04-26T14:27:23Z</time>
     <name>602</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.314005852" lon="12.406268120">
+<time>2005-04-26T14:27:23Z</time>
     <name>603</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.314606667" lon="12.408971786">
+<time>2005-04-26T14:27:23Z</time>
     <name>604</name>
+    <desc>Ordnen Sie sich rechts ein in Richtung Strasse Des 18. Oktober</desc>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.314536594" lon="12.409158535">
+<time>2005-04-26T14:27:23Z</time>
     <name>605</name>
+    <sym>Waypoint</sym>
   </rtept>
   <rtept lat="51.314520836" lon="12.409143448">
 <time>2005-06-24T00:36:57Z</time>
index 8c5db2a43d55f0c3273e427054d4f7751d0066ac..f4495f110109e5a0a1cb98013b5656ca6ac9536c 100755 (executable)
@@ -715,11 +715,17 @@ ${PNAME} -t -i pathaway -f reference/track/pathaway.pdb -o gpx -F ${TMPDIR}/path
 compare ${TMPDIR}/pathaway.gpx reference/track/pathaway.gpx
 
 #
-# Garmin GPS Database .gdb read test
+# Garmin GPS Database .gdb tests
 #
 rm -f ${TMPDIR}/gdb-*
 ${PNAME} -w -r -t -i gdb -f reference/gdb-sample.gdb -o gpx -F ${TMPDIR}/gdb-sample.gpx
 compare reference/gdb-sample.gpx ${TMPDIR}/gdb-sample.gpx
+${PNAME} -w -r -t -i gpx -f reference/gdb-sample.gpx -o gdb,ver=1 -F ${TMPDIR}/gdb-sample.gdb
+${PNAME} -w -r -t -i gdb -f ${TMPDIR}/gdb-sample.gdb -o gpx -F ${TMPDIR}/gdb-sample.gpx
+#
+# Because of Garmin coordinates storage gpx is not good for this test
+# compare reference/gdb-sample.gpx ${TMPDIR}/gdb-sample.gpx
+#
 
 #
 # Vito Navigator II .smt tests